package com.glsc.ngateway.platform.service.itflow.flowstrategy.equipmentModify.taskPostHandler;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSON;
import com.glsc.ngateway.common.api.common.enums.RabbitExcQueConstant;
import com.glsc.ngateway.common.base.domain.mysql.gateway.platform.it.ItCloudDevice;
import com.glsc.ngateway.common.base.domain.mysql.gateway.platform.it.ItServerDevice;
import com.glsc.ngateway.common.base.domain.mysql.gateway.platform.it.ItVirtualDevice;
import com.glsc.ngateway.common.base.domain.mysql.gateway.platform.flow.FlowFormEquipmentModify;
import com.glsc.ngateway.common.base.domain.mysql.gateway.platform.flow.FlowFormEquipmentModifyCloudDeviceDetail;
import com.glsc.ngateway.common.base.domain.mysql.gateway.platform.flow.FlowFormEquipmentModifyServerDetail;
import com.glsc.ngateway.common.base.domain.mysql.gateway.platform.flow.FlowFormEquipmentModifyVirtualDeviceDetail;
import com.glsc.ngateway.common.api.flowable.dto.task.doTaskParam.equipment.EquipmentPassParamDto;
import com.glsc.ngateway.common.api.flowable.dto.task.doTaskParam.equipment.EquipmentRejectParamDto;
import com.glsc.ngateway.common.api.flowable.dto.task.formData.equipment.EquipmentModifyTaskFormDataDto;
import com.glsc.ngateway.common.api.flowable.dto.task.formData.equipment.domainDto.FlowFormEquipmentModifyDto;
import com.glsc.ngateway.common.api.flowable.dto.task.message.EquipmentFlowMessageDto;
import com.glsc.ngateway.common.api.flowable.resp.ResponseSituationDto;
import com.glsc.ngateway.common.base.exception.PlatformException;
import com.glsc.ngateway.common.base.repo.mysql.gateway.platform.FlowFormEquipmentModifyCloudDeviceRepo;
import com.glsc.ngateway.common.base.repo.mysql.gateway.platform.FlowFormEquipmentModifyRepo;
import com.glsc.ngateway.common.base.repo.mysql.gateway.platform.FlowFormEquipmentModifyServerRepo;
import com.glsc.ngateway.common.base.repo.mysql.gateway.platform.FlowFormEquipmentModifyVirtualDeviceRepo;
import com.glsc.ngateway.platform.service.FlowCommonService;
import com.glsc.ngateway.platform.service.it.CloudService;
import com.glsc.ngateway.platform.service.it.ServerService;
import com.glsc.ngateway.platform.service.it.VirtualService;
import com.glsc.ngateway.platform.service.itflow.flowstrategy.AbstractHandlerHelper;
import com.glsc.ngateway.platform.utils.MqUtil;
import com.glsc.ngateway.common.base.enums.itflow.ITFlowStatus;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.validation.constraints.NotNull;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 设备变更节点辅助类
 */
@Component
public class EMStepHandlerHelper extends AbstractHandlerHelper {

    @Autowired
    private ServerService serverService;

    @Autowired
    private VirtualService virtualService;

    @Autowired
    private CloudService cloudService;

    @Autowired
    private FlowFormEquipmentModifyServerRepo modifyServerRepo;

    @Autowired
    private FlowFormEquipmentModifyCloudDeviceRepo modifyCloudServerRepo;

    @Autowired
    private FlowFormEquipmentModifyVirtualDeviceRepo modifyVirtualDeviceRepo;

    @Autowired
    private FlowFormEquipmentModifyRepo equipmentModifyRepo;

    @Autowired
    private FlowCommonService flowCommonService;

    /**
     * 最后审批后置处理
     */
    protected void endTaskAfterHandle(EquipmentPassParamDto<FlowFormEquipmentModifyDto, EquipmentModifyTaskFormDataDto> param, String operator, @NotNull String mqCodeKey) {
        ResponseSituationDto processInfo = flowCommonService.getProcessInfo(param.getProcessId());
        if (io.jsonwebtoken.lang.Collections.isEmpty(processInfo.getCurrentTaskInfoDtoList())) {
            EquipmentFlowMessageDto message = new EquipmentFlowMessageDto();
            FlowFormEquipmentModify modify = equipmentModifyRepo.findByProcessId(param.getProcessId());
            message.setMainFormId(modify.getId());
            message.setDefineKey(mqCodeKey);
            message.setOperator(operator);
            MqUtil.sendMessage(RabbitExcQueConstant.AMPRODUCT_EXCHANGE_DEFAULT, RabbitExcQueConstant.AMPRODUCT_QUEUE_GATEWAY_FLOW_REMIND, message);
        }
    }

    /**
     * 驳回后置处理方法
     */
    protected void afterHandle(@NotNull EquipmentRejectParamDto param, @NotNull String operator) {
        List<FlowFormEquipmentModify> formDataList = equipmentModifyRepo.findAllByProcessId(param.getProcessId());
        formDataList.forEach(f->{
            f.setUpdateAccount(operator);
        });
        equipmentModifyRepo.saveAll(formDataList);
    }

    public void modifyEquipment(Long mainFormId) {
        FlowFormEquipmentModify modify = equipmentModifyRepo.findById(mainFormId)
                .orElseThrow(()->PlatformException.error(String.format("设备变更，消息处理异常：未找到主表数据， %s", mainFormId)));
        //幂等
        if (modify.getIsClose() == 0) {
            //修改服务器设备
            modifyServer(mainFormId);
            //修改虚拟机
            modifyVirtualDevice(mainFormId);
            //修改云平台
            modifyCloudServer(mainFormId);
            modify.setStatus(ITFlowStatus.END.getCode());
            modify.setIsClose(1);
            equipmentModifyRepo.save(modify);
        }
    }

    /**
     * 修改服务器，（表格之外的不作修改）
     */
    private void modifyServer(@NotNull Long modifyId) {
        List<FlowFormEquipmentModifyServerDetail> serverList = modifyServerRepo.findByEquipmentModifyId(modifyId);
        if (CollectionUtil.isEmpty(serverList)) {
            return;
        }
        List<ItServerDevice> newServerList = serverList.stream().map(s -> {
                    if (Objects.isNull(s.getDevId())) {
                        throw PlatformException.error("设备id为空", false, false);
                    }
                    ItServerDevice oldServer = serverService.findByDevId(String.valueOf(s.getDevId()));
                    if (StringUtils.isNotBlank(s.getIpListModifiedStr())) {
                        //修改ip1-4
                        List<String> ipListModified = StringUtils.isNotBlank(s.getIpListModifiedStr()) ? JSON.parseArray(s.getIpListModifiedStr(), String.class) : Collections.emptyList();
                        //先清空ip1-4
                        oldServer.setIp1(null);
                        oldServer.setIp2(null);
                        oldServer.setIp3(null);
                        oldServer.setIp4(null);
                        if (CollectionUtil.isNotEmpty(ipListModified)) {
                            switch (ipListModified.size()) {
                                //最多4个
                                case 4:
                                    oldServer.setIp4(ipListModified.get(3));
                                    oldServer.setIp3(ipListModified.get(2));
                                    oldServer.setIp2(ipListModified.get(1));
                                    oldServer.setIp1(ipListModified.get(0));
                                    break;
                                case 3:
                                    oldServer.setIp3(ipListModified.get(2));
                                    oldServer.setIp2(ipListModified.get(1));
                                    oldServer.setIp1(ipListModified.get(0));
                                    break;
                                case 2:
                                    oldServer.setIp2(ipListModified.get(1));
                                    oldServer.setIp1(ipListModified.get(0));
                                    break;
                                case 1:
                                    oldServer.setIp1(ipListModified.get(0));
                                    break;
                                default:
                                    break;
                            }
                        }
                    }
                    //系统业务
                    oldServer.setBusinessName(s.getBusinessNameModified());
                    //应用明细
                    oldServer.setApplicationDetail(s.getApplicationDetailModified());
                    //操作系统
                    oldServer.setOperationSys(s.getOperationSysModified());
                    //CPU
                    oldServer.setCpu(s.getCpuModified());
                    //内存
                    oldServer.setMemory(s.getMemoryModified());
                    return oldServer;
                })
                .collect(Collectors.toList());
        newServerList.forEach(server -> serverService.addOrUpdateServer(server));
    }

    /**
     * 修改虚拟机，（表格之外的不作修改）
     */
    private void modifyVirtualDevice(@NotNull Long modifyId) {
        List<FlowFormEquipmentModifyVirtualDeviceDetail> virtualDeviceList = modifyVirtualDeviceRepo.findByEquipmentModifyId(modifyId);
        if (CollectionUtil.isEmpty(virtualDeviceList)) {
            return;
        }
        List<ItVirtualDevice> newVirtualDeviceList = virtualDeviceList.stream().map(v -> {
                    if (Objects.isNull(v.getDevId())) {
                        throw PlatformException.error("虚拟机id为空", false, false);
                    }
                    ItVirtualDevice oldVirtual = virtualService.findByDevId(v.getDevId());
                    if (StringUtils.isNotBlank(v.getIpListModifiedStr())) {
                        //修改ip1-4
                        List<String> ipListModified = StringUtils.isNotBlank(v.getIpListModifiedStr()) ? JSON.parseArray(v.getIpListModifiedStr(), String.class) : Collections.emptyList();
                        //先清空ip1-4
                        oldVirtual.setIp1(null);
                        oldVirtual.setIp2(null);
                        oldVirtual.setIp3(null);
                        oldVirtual.setIp4(null);
                        if (CollectionUtil.isNotEmpty(ipListModified)) {
                            switch (ipListModified.size()) {
                                //最多4个
                                case 4:
                                    oldVirtual.setIp4(ipListModified.get(3));
                                case 3:
                                    oldVirtual.setIp3(ipListModified.get(2));
                                case 2:
                                    oldVirtual.setIp2(ipListModified.get(1));
                                case 1:
                                    oldVirtual.setIp1(ipListModified.get(0));
                            }
                        }
                    }
                    //业务系统
                    oldVirtual.setBusinessName(v.getBusinessNameModified());
                    //应用明细
                    oldVirtual.setApplicationDetail(v.getApplicationDetailModified());
                    //环境
                    oldVirtual.setMachineArea(v.getMachineAreaModified());
                    //操作系统
                    oldVirtual.setOperationSys(v.getOperationSysModified());
                    //CPU
                    oldVirtual.setCpu(v.getCpuModified());
                    //内存
                    oldVirtual.setMemory(v.getMemoryModified());
                    return oldVirtual;
                })
                .collect(Collectors.toList());
        newVirtualDeviceList.forEach(virtual -> virtualService.addOrUpdateVirtual(virtual));
    }

    /**
     * 修改云平台，（表格之外的不作修改）
     */
    private void modifyCloudServer(@NotNull Long modifyId) {
        List<FlowFormEquipmentModifyCloudDeviceDetail> cloudDeviceList = modifyCloudServerRepo.findByEquipmentModifyId(modifyId);
        if (CollectionUtil.isEmpty(cloudDeviceList)) {
            return;
        }
        List<ItCloudDevice> newCloudDeviceList = cloudDeviceList.stream().map(c -> {
                    if (Objects.isNull(c.getDevId())) {
                        throw PlatformException.error("虚拟机id为空", false, false);
                    }
                    ItCloudDevice oldCloud = cloudService.findByDevId(c.getDevId());
                    //操作系统
                    oldCloud.setOperationSys(c.getOperationSysModified());
                    //CPU
                    oldCloud.setCpu(c.getCpuModified());
                    //内存
                    oldCloud.setMemory(c.getMemoryModified());
                    //业务系统
                    oldCloud.setBusinessName(c.getBusinessNameModified());
                    return oldCloud;
                })
                .collect(Collectors.toList());
        newCloudDeviceList.forEach(cloud -> cloudService.addOrUpdateCloud(cloud));
    }
}
